/**
 * @file main.c
 * @brief
 * @date Wed, Sep  5, 2018  5:19:05 PM
 * @author liqiang
 *
 * @addtogroup
 * @ingroup
 * @details
 *
 * @{
 */

/*********************************************************************
 * INCLUDES
 */
#include "rwip_config.h" // RW SW configuration

#include "arch.h"      // architectural platform definitions
#include <stdlib.h>    // standard lib functions
#include <stddef.h>    // standard definitions
#include <stdint.h>    // standard integer definition
#include <stdbool.h>   // boolean definition
#include <stdio.h>
#include "rwip.h"      // RW SW initialization
#include "dbg.h"
#include "peripheral.h"
#include "sysdump.h"
#include "app.h"
#include "pmu.h"
#include "application.h"
#include "rwapp_config.h"
#include "gpio_uart.h"
#include "device.h"
#include "pin.h"

const uint8_t fw_version_infor_code[] __attribute__((section(".ARM.__at_0x00447F00"))) = {FIRMWARE_VER}; // RO
const uint8_t hw_version_infor_code[] __attribute__((section(".ARM.__at_0x00447F20"))) = {HARDWARE_VER}; // RO
const uint8_t DeviceType_infor_code[] __attribute__((section(".ARM.__at_0x00447F40"))) = {DEV_TYPE};     // RO

/*********************************************************************
 * MACROS
 */

//#define PIN_GPIO2                    2
//#define PIN_GPIO3                    3
#define PIN_UART0_TX                    5//--

#define DEBUG_UART_BAUDRATE             921600

/*********************************************************************
 * TYPEDEFS
 */


/*********************************************************************
 * CONSTANTS
 */


/*********************************************************************
 * LOCAL VARIABLES
 */


static co_timer_t simple_timer;

/*********************************************************************
 * GLOBAL VARIABLES
 */


/*********************************************************************
 * LOCAL FUNCTIONS
 */

#ifdef BLE_RF_ELLISYS_SCRATCH_PACKAGE
#define RF_TX_PIN	24
#define	RF_RX_PIN	25
void rf_TxRx_pin(void)
{
	
 pinmux_config(RF_TX_PIN, PINMUX_GPIO_MODE_CFG); //tx pin
 pmu_pin_mode_set(BIT_MASK(RF_TX_PIN), PMU_PIN_MODE_PP); //tx pin
 gpio_set_direction(BIT_MASK(RF_TX_PIN), GPIO_OUTPUT); //tx pin
 gpio_write(BIT_MASK(RF_TX_PIN), GPIO_LOW); //tx pin

 pinmux_config(RF_RX_PIN, PINMUX_GPIO_MODE_CFG); // rx pin
 pmu_pin_mode_set(BIT_MASK(RF_RX_PIN), PMU_PIN_MODE_PP); // rx pin
 gpio_set_direction(BIT_MASK(RF_RX_PIN), GPIO_OUTPUT); // rx pin
 gpio_write(BIT_MASK(RF_RX_PIN), GPIO_LOW); // rx pin

 rf_txrx_pin_enable(1, RF_TX_PIN, RF_RX_PIN, 0);
}
#endif
void sys_clock_init(void);

static void peripheral_init(void)
{
    // Init GPIO
    gpio_open();
    #ifdef USE_UART
    // Init UART
    pinmux_config(PIN_UART0_TX, PINMUX_UART0_SDA_O_CFG);    //tx
    pmu_pin_mode_set(BITMASK(PIN_UART0_TX), PMU_PIN_MODE_PP);
    uart_open(HS_UART0, DEBUG_UART_BAUDRATE, UART_FLOW_CTRL_DISABLED, NULL);
    #elif defined(USE_GPIO_UART)
    gpio_uart_init();
    #endif 
}

static void peripheral_restore(void)
{
    #ifdef BLE_RF_ELLISYS_SCRATCH_PACKAGE
    rf_txrx_pin_enable(1, RF_TX_PIN, RF_RX_PIN, 0);
	#endif
    sys_clock_init();
    #ifdef USE_UART
    // Init UART
    uart_open(HS_UART0, DEBUG_UART_BAUDRATE, UART_FLOW_CTRL_DISABLED, NULL);
    #elif defined(USE_GPIO_UART)
    gpio_uart_init();
    #endif 
    // Set PendSV to lowest possible priority
    NVIC_SetPriority(PendSV_IRQn, 0xff);
}

static void hardware_init(void)
{	
    pmu_pin_mode_set(~UN_USED_IO_MASK, PMU_PIN_MODE_PU);  //未使用的IO，配置为上拉

    /* NB模组复位， 高电平有效 */
//    pinmux_config(2, PINMUX_GPIO_MODE_CFG);
//    pmu_pin_mode_set(BITMASK(2), PMU_PIN_MODE_PP);
//    gpio_write(BITMASK(2),GPIO_LOW);  
//    gpio_set_direction(BITMASK(2), GPIO_OUTPUT);
    /* GPIO2和GPIO3引脚在6621CA版本必须输出低，因内部有下拉 */
    // pinmux_config(PIN_GPIO2, PINMUX_GPIO_MODE_CFG);
    // pinmux_config(PIN_GPIO3, PINMUX_GPIO_MODE_CFG);
    // pmu_pin_mode_set(BITMASK(PIN_GPIO2), PMU_PIN_MODE_PP);
    // pmu_pin_mode_set(BITMASK(PIN_GPIO3), PMU_PIN_MODE_PP);
    // gpio_write(BITMASK(PIN_GPIO2), GPIO_LOW);
    // gpio_write(BITMASK(PIN_GPIO3), GPIO_LOW);

#ifndef CONFIG_GPIO1_ABSENT
    pmu_pin_mode_set_ex(0xFF, PMU_PIN_MODE_PU);
#endif

    peripheral_init();
}




static void power_sleep_event_handler(co_power_sleep_state_t sleep_state, co_power_status_t power_status)
{
    switch(sleep_state)
    {
        case POWER_SLEEP_ENTRY:
					HS_PMU->RAM_PM_1 = 0X103;//TODO:
            break;

        case POWER_SLEEP_LEAVE_TOP_HALF:
            peripheral_restore();
            break;

        case POWER_SLEEP_LEAVE_BOTTOM_HALF:
            break;
    }
}

static uint8_t sleepTimeCount = 0;
static void simple_timer_handler(co_timer_t *timer, void *param)
{
    //sysdump();
    log_debug("simeple timer running\n");
    sleepTimeCount++;

    if(sleepTimeCount % 10 == 0)
    {
        pmu_lowpower_allow(PMU_LP_USER); //< 用户允许休眠
        co_timer_del(&simple_timer);
    }

    if(sleepTimeCount == 100)
    {
        sleepTimeCount = 1;
    }
}

static void ble_stack_config(void)
{
    // Disable WDT
    wdt_enable(0);

    #ifdef DCDC_ENABLE
    // Enable DCDC
    pmu_dcdc_enable(true);
    #else
    // Enable LDO
    pmu_dcdc_enable(false);
    #endif

    // Power down xtal32k in deep sleep mode
	pmu_32k_enable_in_deep_sleep(false);//true 表示进入深睡眠时32k启动，唤醒的时候快

    // Select 32k clock for stack
    //pmu_xtal32k_change_param(15, 1);
    #ifdef EXTERNAL_32K
    pmu_select_32k(PMU_32K_SEL_32768HZ_XTAL);
    #else
    pmu_select_32k(PMU_32K_SEL_RC); 
    #endif
    // xtal32m param
    pmu_xtal32m_change_param(XTAL32M_CTUNE_DEFAULT);

    // ultra sleep mode enable
    co_power_ultra_sleep_mode_enable(false); //是否允许进入超深休模式 

    // Enable sleep, SWD will be closed.
    co_power_sleep_enable(true);
		
	//pmu_ram_power_off_invalid_block();//进入睡眠模式的时候关闭不使用的RAM
}

static co_power_status_t power_sleep_status_handler(void)
{
    pmu_lowpower_peripheral_t lpp = pmu_lowpower_prevent_status();

    if(lpp & PMU_LP_USER)
    {
        //< ÓÃ»§½ûÖ¹Ë¯Ãß
        return POWER_ACTIVE;
    }
    else
    {
        //< ÓÉSDK¾ö¶¨ÊÇ·ñË¯Ãß
        return pmu_power_status();
    }
}
void sys_clock_init(void)
{
    #ifdef CONFIG_HS6621P
    cpm_set_clock_div(CPM_SF1_CLK,2);
    cpm_set_clock_div(CPM_SF0_CLK,2);
    cpm_set_clock_div(CPM_CPU_CLK,0);
    pmu_pll_startup(128);
    #elif  CONFIG_HS6621C
    cpm_set_clock_div(CPM_CPU_CLK,1);
    pmu_xtal32m_x2_startup();
    #endif
}

/*********************************************************************
 * PUBLIC FUNCTIONS
 */
extern const char library_compile_time[];
int main(void)
{
    sys_clock_init();
    sc.lpclk_drift = 1000;//蓝牙RX信号提前打开
    ble_stack_config();

    hardware_init();

    rwip_init(RESET_NO_ERROR);

    co_power_register_user_status(power_sleep_status_handler);
    co_power_register_sleep_event(power_sleep_event_handler);

    pmu_lowpower_prevent(PMU_LP_USER);//禁止休眠

    log_debug("running %d\n", pmu_reboot_reason());
    log_debug("BLE_LIB_SVN %s\n", library_compile_time);
    log_debug("firmware version:%s\r\n", FIRMWARE_VER);
    log_debug("compile time:%s %s\r\n",__DATE__, __TIME__);

    #if (CONFIG_MP_TEST_ENABLE && CONFIG_FREQ_CALIB_ENABLE)
    uint8_t  xtal32m_ctune = 0;
    uint16_t len           = 1;
    if (nvds_get(NVDS_TAG_XTAL32M_CTUNE, &len, &xtal32m_ctune) == NVDS_OK)
    {
        log_debug("\n nvds ok");
        if (xtal32m_ctune <= 31)
            app_env.xtal32m_ctune = xtal32m_ctune;
    }
    else
    {
        log_debug("\n nvds fail");
        app_env.xtal32m_ctune = XTAL32M_CTUNE_DEFAULT;
        nvds_put(NVDS_TAG_XTAL32M_CTUNE, 1, &app_env.xtal32m_ctune);
    }
    pmu_xtal32m_change_param(app_env.xtal32m_ctune);

    log_debug("Current xtal32 ctune: %d", app_env.xtal32m_ctune);
    #endif
	//#ifdef BLE_ENABLE
    appm_init();
    //#endif 
    
    #ifdef BLE_RF_ELLISYS_SCRATCH_PACKAGE
    rf_TxRx_pin();
	#endif

    // co_timer_set(&simple_timer, 1000, TIMER_REPEAT, simple_timer_handler, NULL);

    Device_Init();
    OSAL_Init();
    OSAL_Running();
}

/** @} */

// vim: fdm=
